
fun_Max = '''function MAX(int number[], int n, int Rvalue)
{
    frame(i) and
    (
        int i<==0 and Rvalue 0;
        while(i<n)
        {
            if(Rvalue<number[i]) then {Rvalue := number[i]}
        }
    )
}; '''

fun_Bakery = '''function Bakery(int tNum, int number[], int choosing[])
{
    frame(j,temp) and
    (
        int j<==0 and int temp and skip;
        choosing[tNum] :=1;
        temp := 1+ extern MAX (number, 5, Rvalue);
        number[tNum] := temp;
        choosing[tNum] := 0;
        while(j<5)
        {
            await(choosing[j] = 0);
            await (!(number[j]!=0 AND (number[j]<number[tNum] OR (number[j]=number[tNum AND j<tNum]))));
            j := j+1
        }
    )
};'''

# 1. the translation of textFile operation


fun_storedata = '''function StoreData(FILE* fp)
{
    frame(i,brk) and
    (
        int i<==0, brk<==0 and skip;
        while(i<5 AND brk=0)
        {
            if(lineData[i].order=1)then{brk:=1}else{i:=i+1}
        };
        lineData[i].data[0]:=(char*)malloc(bufferSize*sizeof(char));
        fgets(lineData[i].data[0],bufferSize,fp) and skip;
        lineData[i].order<==2 and skip
    )
};'''
fun_read = '''function ReadWords()
{{
    frame(fp) and
    (
        FILE *fp <== fopen("{0}", "r") and skip;
        if(fp = NULL) then
        {{error:=1 and output("{0} cannot be opened.")}}
        else
        {{
            while(error = 0 AND feof(fp) = 0)
            {{
                await(lineData[0].order=1 OR lineData[1].order=1 OR lineData[2].order=1 OR lineData[3].order=1 OR lineData[4].order=1);
                StoreData(fp)
            }}
        }};
        readOver:=1;
        fclose(fp) and skip
    )
}};'''.format(datafile)


# 2. the translation of filter operation

def getcondition(RDDcontent):
    if '>' in RDDcontent:
        return '>' + RDDcontent.split('>')[len(RDDcontent.split('>'))-1]
    if '<' in RDDcontent:
        return '<' + RDDcontent.split('<')[len(RDDcontent.split('>'))-1]
    if '==' in RDDcontent:
        return '=' + RDDcontent.split('==')[len(RDDcontent.split('>'))-1]
    if '!=' in RDDcontent:
        return '!=' + RDDcontent.split('!=')[len(RDDcontent.split('>'))-1]

# RDDcontent is an anonymous function of the filter operation
def dealfilter1(RDDcontent):
    if 'split' in RDDcontent:
        split_in = re.findall(r"[(](.*?)[)]", RDDcontent)[0]
        if '.length' in RDDcontent:
            condition = getcondition(RDDcontent)
            fun_trans = '''function filterFormatCov(char* buf[],int tNum,int length)
                           {{
                               frame(i,k) and
                               (
                                   if (length {0}) then
                                   {{
                                        int i<==0, k<==0 and skip;
                                        while(buf[k]!=NULL)
                                        {{

                                             if(strcmp(buf[k],NULL)!=0)then
                                            {{
                                                lineData[tNum].data[i]:=buf[k];
                                                i:=i+1
                                            }};
                                            k:=k+1
                                        }};
                                        lineData[tNum].order:=lineData[tNum].order +1
                                    }}else
                                    {{
                                        lineData[tNum].order:=1
                                    }}
                               )
                           }};
                           function filtertrans(int sign)
                           {{
                               frame(str,buf,k) and
                               (
                                    char str[1000] and char* buf[100] and int k<==0 and skip;
                                    strcpy(str,lineData[sign].data[0]) and skip;
                                    buf[k]:=strtok(str, {1});
                                    while(buf[k]!=NULL)
                                    {{
                                         k:=k+1;
                                         buf[k]:=strtok(NULL, {1})
                                    }};
                                    k:=k+1;
                                    filterFormatCov(buf,sign,k)

                               )
                           }};'''.format(condition,split_in)
            return fun_trans

fun_filter1 = '''function Filter(int tNum,int n)
{
     frame(i,brk) and
    (
        int i<==0 and skip;
        int brk <==0 and skip;
        while(lineData[0].order=tNum OR lineData[1].order=tNum OR lineData[2].order=tNum OR lineData[3].order=tNum OR lineData[4].order=tNum OR readOver=0)
        {
            Bakery(n, number,choose);
            await(lineData[0].order=tNum OR lineData[1].order=tNum OR lineData[2].order=tNum OR lineData[3].order=tNum OR lineData[4].order=tNum OR readOver=1);
            i := 0;
            brk := 0;
            while( i < 5 AND brk = 0)
            {
                if(lineData[i].order = 1 AND parallel[i] = 0) then{
                    bek := 1
                } else {
                    i := i + 1
                }
            };
            parallel[i] := 1;
            number[n] := 0;
            filtertrans(i);
            parallel[i] := 0
        }
    )
};'''



# 3 the translation of map operation

def dealmap1(RDDcontent):
    if 'split' in RDDcontent:
        s = RDDcontent.split('split')[1]
        sign_in = re.findall(r"[(](.*?)[)]", s)[0]
        extract_num = s.split('(')[2][:-1]
        fun_trans = '''function transImplicit_map(int sign)
        {{
            frame(str,buf,k) and
            (
                char str[1000] and char* buf[100] and int k<==0 and skip;
                strcpy(str,lineData[sign].data[0]) and skip;
                buf[k]:=strtok(str, {0});
                while(buf[k]!=NULL)
                {{
                     k:=k+1;
                     buf[k]:=strtok(NULL, {0})
                }};
                lineData[sign].data[0]:=buf[{1}]
            )
        }};'''.format(sign_in,extract_num)
        return fun_trans
    else:
        s = RDDcontent.split('=>')
        if len(s) == 1:
            if s[0][0] == '(' and s[0][-1] == ')':
                s_sign = s[0].split(',')[1][:-1]
                fun_trans = '''function transImplicit_map(int sign)
                {{
                  frame(i) and
                  (
                    int i<==0 and skip;
                    while(lineData[sign].data[i]!=NULL)
                    {{
                        lineData[x].Vaule[i]:={0};
                        i:=i+1
                    }}
                  )
                }};'''.format(s_sign)
                return fun_trans
        if len(s) == 2:
            if s[1][0] == '(' and s[1][-1] == ')':
                s_sign = s[1].split(',')[1][:-1]
                #print(s_sign)
                #print('====')
                fun_trans = '''function transImplicit_map(int sign)
                {{
                    frame(i) and
                    (
                        int i<==0 and skip;
                        while(lineData[sign].data[i]!=NULL)
                        {{
                            lineData[sign].value[i]:={0};
                            i:=i+1
                        }}
                    )
                }};'''.format(s_sign)
                return fun_trans

fun_map1 = '''function Map(int tNum,int n)
{
    frame(i,brk) and
    (
        int i <== 0 and skip;
        int brk <==0 and skip;
        while(lineData[0].order=tNum OR lineData[1].order=tNum OR lineData[2].order=tNum OR lineData[3].order=tNum OR lineData[4].order=tNum OR readOver=0)
        {
            Bakery(n, number,choose);
            await(lineData[0].order=tNum OR lineData[1].order=tNum OR lineData[2].order=tNum OR lineData[3].order=tNum OR lineData[4].order=tNum OR readOver=1);
            i := 0;
            brk := 0;
            while( i < 5 AND brk = 0)
            {
                if(lineData[i].order = 1 AND parallel[i] = 0) then{ 
                    bek := 1
                } else { 
                    i := i + 1
                }
            };
            parallel[i] := 1;
            number[n] := 0;
            filtertrans(i);
            parallel[i] := 0
        }
    )
};'''




# 4 shuffle function - reduceByKey

fun_shuffle = '''function shuffle(int tNum)
{
    frame(i,j,k,l,brk,m,n) and
    (
        int i<==0 ,j<==0 ,k<==0 ,l<==0 ,brk<==0 ,m<==0 ,n<==0 and skip;
        while(lineData[0].order!=1 OR lineData[1].order!=1 OR lineData[2].order!=1 OR lineData[3].order!=1 OR lineData[4].order!=1 OR readOver !=1)
         {
            await(lineData[0].order=tNum OR lineData[1].order=tNum OR lineData[2].order=tNum OR lineData[3].order=tNum OR lineData[4].order=tNum);
            i:=0;
            while(i<5 AND brk=0)
            {
                if(lineData[i].order=tNum)then{brk:=1}else{i:=i+1}
            };
            if(i<5)then
            {
                k:=0;
                while(lineData[i].data[k]!=NULL)
                {
                    end_data1[l].data:=lineData[i].data[k];
                    end_data1[l].idle:=1;
                    if(lineData[i].value[k]!=0)then{end_data1[l].value:=lineData[i].value[k]};
                    l:=l+1;
                    k:=k+1
                };
                lineData[i].order:=1
            }
        };
        while(m<l)
        {
            i:=0;
            if(end_data1[m].idle=1)then
            {
                end_data[n].data:=end_data1[m].data;
                end_data[n].value[i]:=end_data1[m].value;
                end_data[n].idle:=1;
                end_data1[m].idle:=0;
                j:=m+1;
                while(j<1000)
                {
                    if(end_data1[j].idle=1 AND end_data1[j].data = end_data[n].data)then
                    {
                        i:=i+1;
                        end_data[n].value[i]:=end_data1[j].value;
                        end_data1[j].idle:=0
                    };
                    j:=j+1
                };
                n:= n+1
            };
            m:=m+1
        };
        readOver:=0;
        read_num:=0
    )
};'''


#5. the translation of reduceByKey operation

def mark(Implicit):
    for s in Implicit:
        if s == '+':
            return s
        elif s == '-':
            return s
        elif s == '*':
            return s
        elif s == '/':
            return s

def fun_reduceImplicit(implicit):
    fun_reduceBykeyImplicit = '''function reduceImplicit(int sign, int n)
    {
        frame(k,num) and
        (
            int k<==0,num<==0 and skip;
            num:= read_num;
            read_num:=read_num+1;
            number[n] := 0;
            if(end_data[num].idle=1)then
            {
                finaldata[sign].data:=end_data[num].data;
                while(end_data[num].value[k]!=0)
                {
                    finaldata[sign].value:= finaldata[sign].value''' + implicit + '''end_data[num].value[k];
                    k:=k+1
                };
                end_data[num].idle:=0
            }else
            {
                readOver:=1
            }
        )
    };'''
    return fun_reduceBykeyImplicit

fun_reduceBykey = '''function ReduceBykey(int n)
{
    frame(i, brk) and
    (
        int i<==0 and skip;
        int brk <== 0 and skip; 
        while( readOver = 0 )
        {
            Bakery(n, number, choose);
            await(finaldata[0].order=1 OR finaldata[1].order=1 OR finaldata[2].order=1 OR finaldata[3].order=1 OR finaldata[4].order=1 OR readOver=1);
            i := 0;
            brk := 0;
            while( i < 5 AND brk = 0)
            {
                if(finaldata[i].order = 1 AND parallel[i] = 0) then{ 
                    bek := 1
                } else { 
                    i := i + 1
                }
            };
            parallel[i] := 1;
            reduceImplicit(i,n);
            finaldata[i].order := finaldata[i].order + 1；
            parallel[i] := 0
        }
    )
};'''

# 6 the translation of sort operation

def SortImplicit(RDDcontent):
    if '._2' in RDDcontent and 'false' in RDDcontent:
        fun_sortBy = '''function SortBy(int tNum)
        {
            frame(i,brk,l,m,n,temp) and
            (
                int i<==0 ,brk<==0 ,l<==0 and skip;
                while(finaldata[0].order!=1 OR finaldata[1].order!=1 OR finaldata[2].order!=1 OR finaldata[3].order!=1 OR finaldata[4].order!=1 OR readOver !=1)
                 {
                    await(finaldata[0].order=tNum OR finaldata[1].order=tNum OR finaldata[2].order=tNum OR finaldata[3].order=tNum OR finaldata[4].order=tNum);
                    i:=0;
                    while(i<5 AND brk=0)
                    {
                        if(finaldata[i].order=tNum)then{brk:=1}else{i:=i+1}
                    };
                    if(i<5)then
                    {
                        end_data1[l].data:=finaldata[i].data;
                        end_data1[l].idle:=1;
                        end_data1[l].value:=finaldata[i].value;
                        l:=l+1;
                        finaldata[i].order:=1
                    }
                };
                # descend order
                int m<==0,n<==0 and skip;
                collectData temp and skip;
                while( m < l-1)
                {
                    n:=0;
                    while(n<l-1-m)
                    {
                        if(end_data1[n].value<end_data1[n+1])then
                        {
                            temp.data:=end_data1[n].data;
                            temp.value:=end_data1[n].value;
                            end_data1[n].data:=end_data1[n+1].data;
                            end_data1[n].value:=end_data[n+1].value;
                            end_data1[n+1].data:=temp.data;
                            end_data1[n+1].value:=temp.value
                        };
                        n:=n+1
                    };
                    m:=m+1
                }
            )
        };'''
    if '._2' in RDDcontent and 'false' not in RDDcontent:
        fun_sortBy = '''function SortBy(int tNum)
        {
            frame(i,brk,l,m,n,temp) and
            (
                int i<==0 ,brk<==0 ,l<==0 and skip;
                while(finaldata[0].order!=1 OR finaldata[1].order!=1 OR finaldata[2].order!=1 OR finaldata[3].order!=1 OR finaldata[4].order!=1 OR readOver !=1)
                    {
                    await(finaldata[0].order=tNum OR finaldata[1].order=tNum OR finaldata[2].order=tNum OR finaldata[3].order=tNum OR finaldata[4].order=tNum);
                    i:=0;
                    while(i<5 AND brk=0)
                    {
                        if(finaldata[i].order=tNum)then{brk:=1}else{i:=i+1}
                    };
                    if(i<5)then
                    {
                        end_data1[l].data:=finaldata[i].data;
                        end_data1[l].idle:=1;
                        end_data1[l].value:=finaldata[i].value;
                        l:=l+1;
                        finaldata[i].order:=1
                    }
                };
                # ascending order
                int m<==0,n<==0 and skip;
                collectData temp and skip;
                while( m < l-1)
                {
                    n:=0;
                    while(n<l-1-m)
                    {
                        if(end_data1[n].value > end_data1[n+1].value)then
                        {
                            temp.data:=end_data1[n].data;
                            temp.value:=end_data1[n].value;
                            end_data1[n].data:=end_data1[n+1].data;
                            end_data1[n].value:=end_data[n+1].value;
                            end_data1[n+1].data:=temp.data;
                            end_data1[n+1].value:=temp.value
                        };
                        n:=n+1
                    };
                    m:=m+1
                }
            )
        };'''
    return fun_sortBy
        

# 7 the translation of take operation

def fun_take(Implicit):
    fun_Take = '''function Take()
    {{
        frame(i) and
        (
            int i<==0 and skip;
            while(end_data1[i].idle=1)
            {{
                i:=i+1;
                if(i>{0}-1)then
                {{
                    end_data1[i].idle:=0
                }}
            }}
        )
    }};'''.format(Implicit)
    return fun_Take

# 8 the translation of foreach operation

def fun_foreach(Implicit):
    if Implicit == 'println':
        fun_Foreach = '''function Foreach()
        {
            frame(i,str) and
            (
                int i<==0 and skip;
                char str[1000] and skip;
                while(end_data1[i].idle=1)
                {
                    printf("%s\\n",end_data1[i].data) and skip;
                    printf("%d\\n",end_data1[i].value) and skip;
                    i:=i+1
                }
            )
        };'''
        return fun_Foreach
